JS同步与异步
May 17, 2019
JS本身是单线程的,默认当然就是同步的。具体实现原理,请阅这篇文章。但是可以很方便的实现异步函数。同步函数异步化以及异步函数同步化是我们经常遇到的问题,下面逐一解释。
Update on 20190620: 增加async/await
同步函数异步化
- setTimeout
setTimeout(function(){ alert("Hello"); }, 3000);
创造promise。
var promise = new Promise(function(resolve, reject) {
// some heavy opertion
console.log('Heavy operation');
// resolve or reject
resolve(results)
if(err) reject(err, null);
});
console.log(promise);
同样是创造promise,方式稍微不同。
var promise = function(){
var deferred = Q.defer();
// resolve or reject
if(err) {
deferred.reject(err, null);
} else {
deferred.resolve(result);
}
return deferred.promise;
}
- Async/Await
这个新特性是ECMAScript 2017 (ECMA-262)引入的。它几乎是一个革命性的改进,使得JS对异步的支持更加优雅。这篇文章 对此作了很好的总结。
Promise Version:
const makeRequest = () => {
try {
getJSON()
.then(result => {
// this parse may fail
const data = JSON.parse(result)
console.log(data)
})
// uncomment this block to handle asynchronous errors
// .catch((err) => {
// console.log(err)
// })
} catch (err) {
console.log(err)
}
}
Async/Awiat Version:
const makeRequest = async () => {
try {
// this parse may fail
const data = JSON.parse(await getJSON())
console.log(data)
} catch (err) {
console.log(err)
}
}
异步函数同步化
callback是最常用的办法。
some_3secs_function(some_value, function() {
some_5secs_function(other_value, function() {
some_8secs_function(third_value, function() {
//All three functions have completed, in order.
});
});
});
ES6支持promise了,在promise之后利用then来连接确保顺序执行。如果是多个promise,需要在完成前一个promise的同时返回下一个promise,这样可以顺序执行并处理其结果。
这篇文章很好。
new Promise(function(fulfill, reject){
fulfill(result);
}).then(function(result){
// deal with the result of the first promise
}).then(function(){
// start the second promise
return new Promise(function(fulfill, reject){
fulfill(result);
});
}).then(function(result){
//do something with the result of the second promise
}).catch(function(error){
// deal with error
};
Q同样是利用then,逻辑上和上文的Promise一样。
Q.fcall(function(){
// create promise with fcall in step 1
}).then(function(){
// create promise with deferred in step 2
var deferred = Q.defer();
FS.readFile("foo.txt", "utf-8", function (error, text) {
if (error) {
deferred.reject(new Error(error));
} else {
deferred.resolve(text);
}
});
return deferred.promise;
}).then(function (text) {
// Do something with text
}).catch(function (error) {
// Handle any error from all above steps
}).done();
- 另外一个Promises库
没有本质区别,语法稍有不同。
function readFile(filename, enc){
return new Promise(function (fulfill, reject){
fs.readFile(filename, enc, function (err, res){
if (err) reject(err);
else fulfill(res);
});
});
}
function readJSON(filename){
return readFile(filename, 'utf8').then(JSON.parse);
}